/*jslint browser: true, cap: false, glovar: true, passfail: false, undef: false, white: false */
/*global SONGHAY YAHOO */

//Generic JavaScript functions for data validation, binding and HTTP transport.

(function(){

    SONGHAY.ui.DataValidation =
    {
        buildXmlString:function(oForm)
        {
            var vXmlRoot = (arguments.length > 1) ? arguments[1] : 'FormData';
            var vXmlString = '<' + vXmlRoot + '>\n';
            var oElements = null;
            var oElement = null;

            oElements = oForm.getElementsByTagName('input');

            for(var i=0;i<oElements.length;i++)
            {
                oElement = oElements[i];

                switch(oElement.type)
                {
                    case 'checkbox':
                    case 'hidden':
                        vXmlString += '<' + oElement.id + '>' + self.formatXmlStringInput(oElement.value) + '</' + oElement.id + '>\n';
                    break;
                    case 'text':
                        vXmlString += '<' + oElement.id + '><![CDATA[' + self.formatXmlStringInput(oElement.value) + ']]></' + oElement.id + '>\n';
                    break;
                }
            }

            //Handle groups of radio buttons:
            if(arguments.length > 1)
            {
                var oRadioGroupNames = arguments[1];
                for(i=0;i<oRadioGroupNames.length;i++)
                {
                    oElements = oForm.ownerDocument.getElementsByName(oRadioGroupNames[i]);
                    vXmlString += '<' + oRadioGroupNames[i] + '>' + self.formatXmlStringInput(self.getRadioValue(oElements)) + '</' + oRadioGroupNames[i] + '>\n';
                }
            }

            oElements = oForm.getElementsByTagName('select');
            for(i=0;i<oElements.length;i++)
            {
                oElement = oElements[i];
                vXmlString += (oElement.selectedIndex >= 0)?
                '<' + oElement.id + '>' + self.formatXmlStringInput(oElement.options[oElement.selectedIndex].value) + '</' + oElement.id + '>\n' : '';
            }

            oElements = oForm.getElementsByTagName('textarea');
            for(i=0;i<oElements.length;i++)
            {
                oElement = oElements[i];
                vXmlString += '<' + oElement.id + '><![CDATA[' + self.formatXmlStringInput(oElement.value) + ']]></' + oElement.id + '>\n';
            }

            vXmlString += '</' + vXmlRoot + '>\n';

            return vXmlString;
        },

        formatXmlStringInput: function(vXmlString) {

            vXmlString = vXmlString.replace('<>', '&lt;&gt;');

            return vXmlString;
        },

        getFormData:function(oForm)
        {
            /*
                Builds an HTTP post string or an XML string
                based on the ids of form elements.
            */
            var ret = '';
            var vEncode = (arguments.length > 1) ? arguments[1] : true;
            var vEmitXml = (arguments.length > 2) ? arguments[2] : false;
            var vXmlDocName = (arguments.length > 3) ? arguments[3] : 'FormData';
            var v = '';
            var o = null;

            if(vEmitXml) { ret = '\n<' + vXmlDocName + '>\n'; }

            for(var i=0; i < oForm.elements.length; i++)
            {
                if
                (
                    oForm.elements[i].type && (oForm.elements[i].value !== undefined) &&
                    oForm.elements[i].type.toLowerCase().match(/checkbox|hidden|password|radio|text|textarea/)
                )
                {
                    o = oForm.elements[i];
                    if(vEmitXml)
                    {
                        if(vEncode)
                        { ret += '\n<' + o.id + '>' + encodeURI(o.value) + '</' + o.id + '>\n'; }
                        else
                        { ret += '\n<' + o.id + '>' + o.value + '</' + o.id + '>\n'; }
                    }
                    else
                    {
                        if(vEncode)
                        { ret += (ret.length === 0) ? o.id + '=' + encodeURI(o.value) : '&' + o.id + '=' + encodeURI(o.value); }
                        else
                        { ret += (ret.length === 0) ? o.id + '=' + o.value : '&' + o.id + '=' + o.value; }
                    }
                }

                if(oForm.elements[i].tagName.toLowerCase() == 'select')
                {
                    v = oForm.elements[i].options[oForm.elements[i].selectedIndex].value;

                    o = oForm.elements[i];
                    if(vEmitXml)
                    {
                        if(vEncode)
                        { ret += '\n<' + o.id + '>' + encodeURI(v) + '</' + o.id + '>\n'; }
                        else
                        { ret += '\n<' + o.id + '>' + v + '</' + o.id + '>\n'; }
                    }
                    else
                    {
                        if(vEncode)
                        { ret += (ret.length === 0) ? o.id + '=' + encodeURI(v) : '&' + o.id + '=' + encodeURI(v); }
                        else
                        { ret += (ret.length === 0) ? o.id + '=' + v : '&' + o.id + '=' + v; }
                    }
                }
            }

            if(vEmitXml) { ret += '\n</' + vXmlDocName + '>\n'; }

            return ret;
        },

        getOptionsIndex:function(oSelect,vData)
        {
            //This function binds the select element to the specified data:
            for(var i = 0; i < oSelect.options.length; i++)
            {
                if(oSelect.options[i].value == vData) { return i; }
            }
            return 0;
        },

        getRadioValue:function(oRadio)
        {
            //This function returns the value of the checked radio button in an array of radio buttons.
            var vData = '';

            for(var i = 0; i < oRadio.length; i++)
            {
                if(oRadio[i].checked)
                {
                    vData = oRadio[i].value;
                }
            }

            return vData;
        },

        getWildCard:function(vCode,vString,vWildCard)
        {
            //Default to SQL Server (ADO/ADO.NET) WildCard:
            vWildCard = (vWildCard.length === 0) ? '%' : vWildCard;

            switch(vCode)
            {
                case '*'://Containing:
                    vString = vWildCard + vString + vWildCard;
                    break;
                case '=*'://Starting with:
                    vString = vString + vWildCard;
                    break;
                case '*='://Ending with:
                    vString = vWildCard + vString;
                    break;
                case '='://Exact:
                    break;
            }
            return vString;
        },

        getXmlElement:function(oElement)
        {
            var vElementString = '';

            var vDefaultValue = (arguments.length > 1) ? arguments[1] : null;
            var vUseCData = (arguments.length > 2) ? arguments[2] : true;
            var vElementName = (arguments.length > 3) ? arguments[3] : null;

            if(oElement && oElement.id && oElement.value && (oElement.value.length > 0))
            {
                vElementName = (vElementName) ? vElementName : oElement.id;

                if(vUseCData)
                {
                    vElementString = '<' + vElementName + '><![CDATA[' + self.formatXmlStringInput(oElement.value) + ']]></' + vElementName + '>\n';
                }
                else
                {
                    vElementString = '<' + vElementName + '>' + self.formatXmlStringInput(oElement.value) + '</' + vElementName + '>\n';
                }
            }
            else
            {
                if(vElementName)
                {
                    vElementString = (vDefaultValue) ? '<' + vElementName + '>' + self.formatXmlStringInput(vDefaultValue) + '</' + vElementName + '>\n' : '<' + vElementName + ' />\n';
                }
                else if(oElement && oElement.id)
                {
                    vElementName = (vElementName) ? vElementName : oElement.id;
                    vElementString = (vDefaultValue) ? '<' + vElementName + '>' + self.formatXmlStringInput(vDefaultValue) + '</' + vElementName + '>\n' : '<' + vElementName + ' />\n';
                }
            }

            return vElementString;
        },

        //Form Validation Functions:
        isEmailValid:function(vFormName,oElement)
        {

            var vValid = false;

            if(oElement === null)
            {
                self.onMessage.fire('A scripting object was not found to validate.\n(Form name: ' + vFormName + ')');
                return false;
            }
            if(oElement.value === null)
            {
                self.onMessage.fire('A scripting object does not have a value property to be validated.\n(Form name: ' + vFormName + ')');
                return false;
            }

            var vPosAtSymbol = oElement.value.indexOf('@');
            var vPosPeriod = oElement.value.lastIndexOf('.');
            var vPosSpace  = oElement.value.indexOf(' ');
            var vLength = oElement.value.length - 1;

            if(
                // '@' in first position
                (vPosAtSymbol < 1) ||

                // '@' in last position
                (vPosAtSymbol == vLength) ||                    

                // Not at least one valid char' between '@' and '.'
                (oElement.value.charAt(vPosAtSymbol + 1) == '.') ||
                (oElement.value.charAt(vPosAtSymbol - 1) == '.') ||

                // Must be at least two valid char's after last '.'
                (vPosPeriod >= vLength - 1) ||

                // No space char's permitted
                (vPosSpace  != -1)
            )
            {                   
                self.onMessage.fire('Please enter a valid e-mail address.\n\nSample: YourName@aol.com',oElement);
                return vValid;
            }
            vValid = true;
            return vValid;
        },

        isNotComplete:function(oElement,vMsg)
        {
            //This function verifies that a text type INPUT value is entered.
            if(oElement === null)
            {
                self.onMessage.fire('A scripting object was not found to validate.');
                return false;
            }
            if(oElement.value === null)
            {
                self.onMessage.fire('A scripting object does not have a value property to be validated.');
                return false;
            }
            if(oElement.value === '')
            {
                self.onMessage.fire('Please complete the following:<br/><br/>&#160;&#160;&#160;&#160;' + vMsg,oElement);
                return true;
            }
            else
            {
                return false;
            }
        },

        isNotNumeric:function(oElement,vMsg)
        {
            //This function verifies that a text type INPUT value is numeric.
            if(oElement === null)
            {
                self.onMessage.fire('A scripting object was not found to validate.');
                return false;
            }
            if(oElement.value === null)
            {
                self.onMessage.fire('A scripting object does not have a value property to be validated.');
                return false;
            }
            if(isNaN(parseInt(oElement.value,10)))
            {
                self.onMessage.fire('Please enter a number here:<br/><br/>&#160;&#160;&#160;&#160;' + vMsg,oElement);
                return true;
            }
            else
            {
                return false;
            }
        },

        isNotSelected:function(oElement,vMsg)
        {

            var vData, vReturn = true;

            //This function verifies OPTION or INPUT (type=radio) values are selected.
            if(oElement === null)
            {
                self.onMessage.fire('A scripting object was not found to validate.');
                vReturn = false;
            }
            if(oElement.length === null)
            {
                self.onMessage.fire('A scripting object does not have a length property to be tested.');
                vReturn = false;
            }

            if(oElement.type === null)
            {
                if(oElement.length > 1)
                {
                    if(oElement[0].type === null)
                    {
                        self.onMessage.fire('A scripting object does not have a type property to be tested.');
                        vReturn = false;
                    }    
                }
                else
                {
                    self.onMessage.fire('A scripting object does not have a type property to be tested.');
                    vReturn = false;
                }
            }

            if(oElement.length > 1)
            {
                if(oElement[0].type == 'radio')
                {
                    for(var i = 0; i < oElement.length; i++)
                    {
                        vData = oElement[i].checked;

                        //Test to break out of loop:
                        if(vData) { i = oElement.length; }
                    }
                    if(vData === false)
                    {
                        self.onMessage.fire('Please complete the following:<br/><br/>&#160;&#160;&#160;&#160;' + vMsg,oElement[0]);
                        return true;
                    }
                    else
                    {
                        vReturn = false;
                    }
                }

                if(oElement.type.indexOf('select') === 0)
                {
                    if(oElement.selectedIndex === 0)
                    {
                        self.onMessage.fire('Please complete the following:<br/><br/>&#160;&#160;&#160;&#160;' + vMsg,oElement);
                        return true;
                    }
                    else
                    {
                        vReturn = false;
                    }
                }
            }

            return vReturn;
        },

        isTextConfirmed:function(oElement1,oElement2,vMsg)
        {
            //This function verifies that text type INPUT or TEXTAREA values between two elements are equal.
            if((oElement1 === null) || (oElement2 === null))
            {
                self.onMessage.fire('A scripting object was not found to validate.');
                return false;
            }
            if((oElement1.value === null) || (oElement2.value === null))
            {
                self.onMessage.fire('A scripting object does not have a value property to be validated.');
                return false;
            }
            if(oElement1.value == oElement2.value)
            {
                return true;
            }
            else
            {
                self.onMessage.fire(vMsg,oElement1);
                return false;
            }
        },

        isTextLength:function(oElement,vMaxLength,vMsg)
        {
            //This function verifies that text type INPUT or TEXTAREA values are the correct length.
            if(oElement === null)
            {
                self.onMessage.fire('A scripting object was not found to validate.');
                return false;
            }
            if(oElement.value === null)
                {
                self.onMessage.fire('A scripting object does not have a value property to be validated.');
                return false;
            }
            if(oElement.value.length > vMaxLength)
                {
                self.onMessage.fire(vMsg + ' is longer than the ' + vMaxLength + ' allowed characters.',oElement);
                return false;
            }
            else { return true; }
        },

        isUniqueOption:function(oSelect,vData)
        {
            //This function verifies that unique OPTION values are selected when MULTIPLE is specified.
            if(oSelect === null)
            {
                self.onMessage.fire('A scripting object was not found to validate.');
                return false;
            }
            if(oSelect.options === null)
            {
                self.onMessage.fire('A scripting object does not have an options property to be validated.');
                return false;
            }
            for(var i = 0; i < oSelect.options.length; i++)
            {
                if(oSelect.options[i].value == vData)
                {
                    vData = 'You have already entered this value:<br/><br/>&#160;&#160;&#160;&#160;' + oSelect.options[i].text;
                    self.onMessage.fire(vData);
                    return false;
                }
            }
            return true;
        }
    };

    //Module-level "this":
    var self = SONGHAY.ui.DataValidation;

    SONGHAY.ui.DataValidation.onMessage = new YAHOO.util.CustomEvent("SONGHAY.ui.DataValidation.onMessage");

})();
